package com.ai.trickycards.widgets

import android.animation.LayoutTransition
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.widget.LinearLayout
import androidx.core.view.isVisible
import com.ai.trickycards.databinding.LayoutChatViewBinding
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class ChatView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {

    private val binding = LayoutChatViewBinding.inflate(LayoutInflater.from(context), this)
    private val scope = CoroutineScope(Dispatchers.Main)
    private var speakJob: Job? = null
    private var speakSpeed = 0L

    init {
        layoutTransition = LayoutTransition()
        setOnClickListener { speakSpeed = 0 }
    }

    fun reset() {
        stopSpeak()
        setMessage("")
        setLeftOption("")
        setRightOption("")
    }

    fun setMessage(text: String): ChatView {
        binding.tvMessage.text = text
        return this
    }

    fun startSpeak(
        textList: List<String>,
        speed: Long = 30,
        startDelay: Long = 0,
        doOnEndDelay: Long = 0,
        doOnEnd: (suspend CoroutineScope.(ChatView) -> Unit)? = null
    ): ChatView {
        stopSpeak()
        binding.tvMessage.text = ""
        Log.i("startSpeak", "--------------\n${textList.joinToString(separator = "\n") { it }}")
        speakSpeed = speed
        speakJob = scope.launch {
            if (startDelay > 0) {
                delay(startDelay)
            }
            textList.forEachIndexed { index, msg ->
                if (index > 0) {
                    binding.tvMessage.append("\n")
                }
                msg.forEach { char ->
                    binding.tvMessage.append(char.toString())
                    delay(speakSpeed)
                }
            }
            if (doOnEndDelay > 0) {
                delay(doOnEndDelay)
            }
            doOnEnd?.invoke(this, this@ChatView)
        }
        return this
    }

    fun stopSpeak() {
        speakJob?.cancel()
    }

    fun setLeftOption(text: String, listener: OnClickListener? = null): ChatView {
        binding.tvOptionLeft.isVisible = text.isNotEmpty()
        binding.tvOptionLeft.text = text
        binding.tvOptionLeft.setOnClickListener(listener)
        setOptionVisible()
        return this
    }

    fun setRightOption(text: String, listener: OnClickListener? = null): ChatView {
        binding.tvOptionRight.isVisible = text.isNotEmpty()
        binding.tvOptionRight.text = text
        binding.tvOptionRight.setOnClickListener(listener)
        setOptionVisible()
        return this
    }

    private fun setOptionVisible() {
        binding.space.isVisible = binding.tvOptionLeft.isVisible || binding.tvOptionRight.isVisible
    }

    override fun onDetachedFromWindow() {
        super.onDetachedFromWindow()
        speakJob?.cancel()
        scope.cancel()
    }
}